#!/usr/bin/perl
#use warnings;

###################################
#
#  Current Version 1.0,  Author is : lyndonguo@gmail.com
#  Hisotry:
#  
#  1.0   2017.04.17  the first Init
#
#
###################################

use Getopt::Std;
use GD;
use Data::Dumper;
use List::Util qw/max min/;
use Cwd;
use POSIX qw(strftime);

$PNG="1500*160:M,5M,20M,300M";   # 定义默认图片的像素，以及4张图的放大倍数。
$start=time();
$CONFIG_FILE="mskg.cfg";  # 默认配置文件
$WORK_DIR="./";  # 默认是当前目录
@HTML_TEMP=<DATA>;  # 一次性读入模板信息。

### default value
if($PNG=~/(\d*)\*(\d*):(\d*)M,(\d*)M,(\d*)M,(\d*)M/){
	$PNG_WIDTH=$1;
	$PNG_HEIGHT=$2;
	$PNG_DAYLIY=$3;  # 表示天图中每根像素的间隔周期
	$PNG_DAYLIY=1 if(!$3);  # 如果没有值，则使用默认值1
	$PNG_WEEKLY=$4;
	$PNG_MONTHLY=$5;
	$PNG_YEARLY=$6;
}

$PNG_TOP=20;
$PNG_LEFT=40;
$PNG_RIGHT=28;  # 此处要Lable 百分比标志。
$PNG_BOTTOM=20;


# 从配置文件的PNG参数扩地图片的像素规格和DWMY图标的放大倍数
$ARGN=@ARGV;  # 命令行参数个数
getopts('f:thv') or usage();
usage() if($ARGN < 1);  # $#ARGV 命令行参数个数-1
usage() if($opt_h);

$CONFIG_FILE=$opt_f if($opt_f);


# Print Usage and exit
sub usage {
   print STDERR <<EOF

   Usage: $0 [ -f mskg.cfg ] [-t] [-v]
          -f config file name (include path)
		  -t test the config file
		  -v print the verbose information.

EOF
;
   exit;
}


########################################################
# Main Function.
########################################################


readconfig($CONFIG_FILE);  # Read Configure, 一个配置文件有多个Item进行进行执行。

$WORK_DIR=getcwd;  # 默认获得当前路径
$WORK_DIR=$CONFIG{Global}{WORKDIR} if defined $CONFIG{Global}{WORKDIR};
$CONFIG{Global}{WORKDIR}=$WORK_DIR unless defined $CONFIG{Global}{WORKDIR};

$PNG=$CONFIG{Global}{PNG} if defined $CONFIG{Global}{PNG};

testconfig() if($opt_t);  # testing the configure syntax.
exit(0) if($opt_t);  # testing the configure syntax.


@configureitem=keys(%CONFIG);

foreach $item(@configureitem){
	next if($item eq "Global");
	print "\n   ......... $item ...........\n" if($opt_v);
	# 获得命令行名，并根据提供的信息，计算是否需要全路径。
	my $commandline=$CONFIG{$item}{CMD};
	$commandline=$WORK_DIR.$CONFIG{$item}{CMD} unless($commandline=~/^\//);
	$CMD_RESULT=getcurrentdatafromcommand($commandline);  #  该函数的返回值第1项为时间=秒，后续为数据项。
	getconfigfromcommandline($item,$CMD_RESULT);   # 程序的返回结果中获得，曲线的Tile，MAX值等。
	
	processitemconfig($item);

	preparetimedata();   # init the timedate. inclue daily,weekly,monthly,and yearly.
	readandprocesstimedate($item); # read the data from *data.log file.
	
	# processtheMaxValues($item);    # 处理最大值问题，如果数据中增量的，则需要计算出最大值先。
	drawandsavepictures($item,"daily");  # draw and save picutres.
	drawandsavepictures($item,"weekly");  # draw and save picutres.
	drawandsavepictures($item,"monthly");  # draw and save picutres.
	drawandsavepictures($item,"yearly");  # draw and save picutres.
	
	savetimedata($item);  # save the new data into data.log file
	updatehtml($item);  # update 
}

$est=time()-$start;
print "   -- EST: $est seconds -- \n\n";

################################  Sub functions  ##################

# get the date string "2016-05-21-06:32:00", base on the seconds from 1970.
sub gettime{
	my $thistime=shift;
	my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($thistime);
	$year += 1900; # $year是从1900开始计数的，所以$year需要加上1900；
	$mon += 1; # $mon是从0开始计数的，所以$mon需要加上1；
	my $datetime = sprintf ("%d-%02d-%02d-%02d:%02d:%02d Week:%02d WeekNum: %02d", $year,$mon,$mday,$hour,$min,$sec,$wday,getweek($thistime));
	return $datetime;
}

sub gethour{  # 获得小时
	my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(shift);
	my $datetime = sprintf ("%02d", $hour);
	return $datetime;
}

sub getmday{  # 获得日期
	my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(shift);
	my $datetime = sprintf ("%02d", $mday);
	return $datetime;
}

sub getmonth{  # 获得月份
	my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(shift);
	$mon += 1; # $mon是从0开始计数的，所以$mon需要加上1；
	my $datetime = sprintf ("%02d", $mon);
	return $datetime;
}

sub getweek{  # 获得星期
	return POSIX::strftime("%V", localtime(shift));
}


sub isFixedHour{  # 判断当前秒数是否为Hour?Week?month or Year.
	my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(shift);
	return 1 if($sec==0 and $min==0);  # is integr hour
	return 0;
}

sub isFixedDay{  # 判断当前秒数是否为Hour?Week?month or Year.
	# my $nowtime=shift;
	my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(shift()+60*$PNG_DAYLIY);
	return 1 if($sec==0 and $min==0 and $hour==0);  # is integr day
	return 0;
}

sub isFixedWeek{  # 判断当前秒数是否为Hour?Week?month or Year.
	my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(shift()+60*$PNG_WEEKLY);
	#print "sec:$sec,min:$min,hour:$hour,mday:$mday,mon:$mon,year:$year,wday:$wday,yday:$yday,isdst:$isdst";
	return 1 if($sec==0 and $min==0 and $hour==0 and $wday==0);  # is integr week, 注意时间间隔
	return 0;
}
sub isFixedWeek4M{  # 判断月数据中是否为星期。
	my $inputtime=shift();
	my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($inputtime);
	# print "         sec:$sec,min:$min,hour:$hour,mday:$mday,mon:$mon,year:$year,wday:$wday,yday:$yday,isdst:$isdst\n";
	#my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(inputtime+60*$PNG_MONTHLY);
	#print "sec:$sec,min:$min,hour:$hour,mday:$mday,mon:$mon,year:$year,wday:$wday,yday:$yday,isdst:$isdst\n";
	return 1 if($sec==0 and $min==0 and $hour==0 and $wday==0);  # is integr week, 注意时间间隔
	return 0;
}

sub isFixedMonth{  # 判断当前秒数是否为Hour?Week?month or Year.
	my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(shift()+60*$PNG_MONTHLY);
	# print "sec:$sec,min:$min,hour:$hour,mday:$mday,mon:$mon,year:$year,wday:$wday,yday:$yday,isdst:$isdst";
	return 1 if($sec==0 and $min==0 and $hour==0 and $mday==1);  # is integr year, 注意时间间隔
	return 0;
}

sub isFixedYear{  # 判断当前秒数是否为Hour?Week?month or Year.
	my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(shift()+60*$PNG_YEARLY);
	# print "sec:$sec,min:$min,hour:$hour,mday:$mday,mon:$mon,year:$year,wday:$wday,yday:$yday,isdst:$isdst";
	return 1 if($sec==0 and $min==0 and $hour==0 and $mon==1);  # is integr year, 注意时间间隔
	return 0;
}




sub readconfig{

	my $configfile=shift;
	open CFGFILE, $configfile or die "  Open file :\" $configfile \" Failed...\n";
	my $newitemflag=0;
	my $session="_";
	while(my $string=<CFGFILE>){
		chop($string);
		$string=~s/^[\s|\t]*//g;  # 删除开头有空白的空白
		$string=~s/[\s|\t]*#.*//g;  # 删除空白，tab + # 的后续内容。
		if($string!~/^$/){  # 非空白行的开始处理
			$session=$1 if($string=~/^\[(.*)\]/);
			$CONFIG{$session}{uc($1)}=$2 if($string=~/(.*?)=(.*)/);
		}
	}
	close CFGFILE;
}
sub testconfig{
	print "\n  Configure file: $CONFIG_FILE\n\n";
	foreach $key(keys %CONFIG){
		# print "  $key";
		foreach $key1(keys %{$CONFIG{$key}}){
			print "  \$CONFIG{$key}{$key1} = $CONFIG{$key}{$key1}\n";
		}
		my $result=getcurrentdatafromcommand($CONFIG{$key}{CMD});
		print "  \$CONFIG{$key}{CMDRESULT} = $result\n";
		print "\n";
	}
}

# read the result from the command line.
sub getcurrentdatafromcommand{
	my $command=shift;
	print "   [DEBUG] running command: $command\n" if($opt_v);
	chop(my $result =`$command`);
	# $result=~s/\n/ /g;  # 删除返回值中的空行，合并成带空格的一行。
	if(length($result) ==0){  # 如果命令没有返回值，则返回-1.
		print "   [ERROR] the command [$command] result is empty!!! \n";
		return -1;
	}
	my $ret=time().",".$result;
	print "   [DEBUG] the command result: $ret\n" if($opt_v);
	return $ret;
}

#########################################3
# 处理子项的配置项，可以用来覆盖默认值。

sub processitemconfig{
	
	my $item=shift;
	# $currenttime 表示当前时间。
	# 测试数据：1491401820(2017-04-05-22:17:00)
	if($CONFIG{$item}{PNG} eq ""){
		print "   [WARN] \'$item\' PNG CONFIG is not configured, the default will be used: $PNG\n";
		$CONFIG{$item}{PNG}=$PNG;
	}
	if($CONFIG{$item}{PNG}=~/(\d*)\*(\d*):(\d*)M,(\d*)M,(\d*)M,(\d*)M/){
		$PNG_WIDTH=$1;
		$PNG_HEIGHT=$2;
		$PNG_DAYLIY=$3;  # 表示天图中每根像素的间隔周期
		$PNG_DAYLIY=1 if(!$3);  # 如果没有值，则使用默认值1
		$PNG_WEEKLY=$4;
		$PNG_MONTHLY=$5;
		$PNG_YEARLY=$6;
	}
	print "   [DEBUG] ==================== CONFIGURE ====================\n" if($opt_v);
	if($opt_v){  # debug the config settings.
		foreach $k(sort(keys %{$CONFIG{$item}})){
			print "   [DEBUG]    \$CONFIG{$item}{$k} = \"$CONFIG{$item}{$k}\"\n";
		}
	}
	print "   [DEBUG] ==================== CONFIGURE ====================\n" if($opt_v);
}

###########################################
#  处理命令行获得，命令的返回值最多9个域（如果有不需要的域，需要返回0，或"-"号,第1个域为当前时间戳，
#  command 的返回值格式有下面几种类型
#  [name=+]8776698[/10240000]
#   name 用显示在第1分区的名称， + 表示该指标是个累加值，需要与上次数据进行统计的，最后一个方括号最大值，如果没有，则会以这个区段的最大值为准。

sub getconfigfromcommandline{
	my $item=shift;
	my $commandresult=shift;  # get the command result.
	my (@ret)=split(/,/,$commandresult);
	for(my $i=1;$i<scalar @ret;$i++){
		next if($ret[$i] eq "" or $ret[$i]=~/\s+/);  # 
		if($ret[$i]=~/(.*?)=(.*)/){
			my $key="V${i}_TITLE";
			$CONFIG{$item}{$key} = $1;
			my $value=$2;
			my($numerator,$denominator)=split(/\//,$value);
			$key="V${i}_MAX";
			$CONFIG{$item}{$key} = $denominator;
			if($numerator=~/(\+{0,1})([\d|\.]*)/){  # 可以处理小数
				# $key="V${i}_INCREMENT";
				$CONFIG{$item}{"V${i}_INCREMENT"} = $1;
				$CONFIG{$item}{"V${i}_VALUE"} = $2;
			}
		}else{  # 没有 = 号，也就指标没有指定指标名称。
			my $value=$ret[$i];
			my($numerator,$denominator)=split(/\//,$value);
			$key="V${i}_MAX";
			$CONFIG{$item}{$key} = $denominator;
			if($numerator=~/(\+{0,1})([\d|\.]*)/){  # 可以处理小数
				# $key="V${i}_INCREMENT";
				$CONFIG{$item}{"V${i}_INCREMENT"} = $1;
				$CONFIG{$item}{"V${i}_VALUE"} = $2;
			}
		}
	}
}
###################################
# init the timedate. inclue daily,weekly,monthly,and yearly.
# 该函数用来生产时间轴默认数据，均为0.
sub	preparetimedata{
	my $currenttime=time();
	
	# 清楚这些预设值。
	undef %DDATALOG;
	undef %WDATALOG;
	undef %MDATALOG;
	undef %YDATALOG;
		
		
	# my $currenttime=1491435060;
	# PNG_WIDTH 宽度，表示图标中像素的个数，也就是记录数
	for(my $i=0;$i<$PNG_WIDTH;$i++){
		# 先处理时间轴的第1个时间
		if($i==0){
			# 获得当前时间的秒数，为了将多余的秒数去除。
			my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($currenttime);
			$dt=(int($currenttime/60/$PNG_DAYLIY))*$PNG_DAYLIY*60;
			# $dt=$currenttime-$sec;
			$wt=(int($currenttime/60/$PNG_WEEKLY))*$PNG_WEEKLY*60;
			$mt=(int($currenttime/60/$PNG_MONTHLY))*$PNG_MONTHLY*60;
			$yt=(int($currenttime/60/$PNG_YEARLY))*$PNG_YEARLY*60;
		}else{
			$dt=$dt-60*$PNG_DAYLIY;
			$wt=$wt-60*$PNG_WEEKLY;
			$mt=$mt-60*$PNG_MONTHLY;
			$yt=$yt-60*$PNG_YEARLY;
		}

		$DDATALOG{$dt}="0,0,0,0,0,0,0,0";
		$WDATALOG{$wt}="0,0,0,0,0,0,0,0";
		$MDATALOG{$mt}="0,0,0,0,0,0,0,0";
		$YDATALOG{$yt}="0,0,0,0,0,0,0,0";
		
		#$I=sprintf("%03d",$i);
		#print "$I . ".gettime($dt)." ".gettime($wt)." ".gettime($mt)." ".gettime($yt)."\n";
	}
} 

############################################
# 从历史文件中读取历史数据，并填充到时间轴上。
sub	readandprocesstimedate{ # read the data from *data.log file.
	my $item=shift;
	open(DATAFILE, "<","$item.data.log") or print " WARNING. $item.data.log is not exist." ;
	my $thefirstline=<DATAFILE>;  # 读取第1行，该行内容要和 $CMD_RESULT进行计算的，计算后要填充到第2行的内容的。
	chop($thefirstline);
	print "   [DEBUG] \$CMD_RESULT: $CMD_RESULT [".gettime(split(/,/,$CMD_RESULT,1))."]\n" if($opt_v);
	print "   [DEBUG] First line : $thefirstline [".gettime(split(/,/,$thefirstline,1))."]\n" if($opt_v);
	while(my $line=<DATAFILE>){
		my($t,$v)=split(/,/,$line,2);
		# print ">>> $t -> $v";
		chop($v);  # 去除尾行回车
		$DDATALOG{$t}=$v if(defined $DDATALOG{$t});
		$WDATALOG{$t}=$v if(defined $WDATALOG{$t});
		$MDATALOG{$t}=$v if(defined $MDATALOG{$t});
		$YDATALOG{$t}=$v if(defined $YDATALOG{$t});
	}
	# 填充完毕后，需要对历史的第一行数据当天的命令行数据进行计算并决定是否填充到时间轴上。
	my @daykeys=keys(%DDATALOG);
	my $thelatesttime=max(@daykeys);
	
	my (@ret)=split(/,/,$CMD_RESULT);
	my (@ret1)=split(/,/,$thefirstline);
	
	$DDATALOG{$thelatesttime}="";
	for(my $i=1;$i<9;$i++){
		my($keyname,$keyvalue,$keymax,$keytype)=parserfield($ret[$i]);
		$keyvalue=0 if($keyvalue eq "");
		## 如果某个collom是一个增量数据，需要在这里计算增量的变化量。
		if($keytype eq "+"){
			my($keyname1,$keyvalue1,$keymax1,$keytype1)=parserfield($ret1[$i]);
			$keyvalue=int(abs($keyvalue-$keyvalue1)/($ret[0]-$ret1[0]));  # 计算 Delta 变化量
		}
		
		if($i==1){
			$DDATALOG{$thelatesttime}=$keyvalue;
		}else{
			$DDATALOG{$thelatesttime}=$DDATALOG{$thelatesttime}.",".$keyvalue;
		}
	}
	close(DATAFILE);
	print "   [DEBUG] First pixel: $thelatesttime,$DDATALOG{$thelatesttime} [".gettime($thelatesttime)."]\n" if($opt_v);
}

##########################################
# parser field

sub parserfield{
	my $field=shift;
	
	my $keyname;  # 返回值的名字
	my $keyvalue;  # 返回值
	my $keymax;   # 返回最大值
	my $keytype;  # 返回类型
	
	if($field=~/(.*?)=(.*)/){  #分析是否带key名字
		$keyname=$1;
		my $value=$2;
		my($numerator,$denominator)=split(/\//,$value);
		$keymax = $denominator;
		if($numerator=~/(\+{0,1})([\d|\.]*)/){
			$keyvalue=$2;
			$keytype=$1;
		}
	}else{  # 没有 = 号，也就指标没有指定指标名称。
		my($numerator,$denominator)=split(/\//,$field);
		$keymax = $denominator;
		if($numerator=~/(\+{0,1})([\d|\.]*)/){
			$keyvalue=$2;
			$keytype=$1;
		}
	}
	return($keyname,$keyvalue,$keymax,$keytype);
}

#  创建一个Image对象，准备在其上面构建图表

sub createimagetemplate{
	
	# create a new image,左右各添加2个像素， 每个 图表的实际数据
	$WIDTH=$PNG_WIDTH+2+$PNG_LEFT+$PNG_RIGHT;  # 宽
	$HEIGHT=$PNG_HEIGHT+$PNG_TOP+$PNG_BOTTOM;  # 高
	$IM_HANDLER = new GD::Image($WIDTH,$HEIGHT);  

	# allocate some colors
	$COLOR_white = $IM_HANDLER->colorAllocate(255,255,255);
	$COLOR_black = $IM_HANDLER->colorAllocate(0,0,0);       
	$COLOR_red = $IM_HANDLER->colorAllocate(255,0,0);      
	$COLOR_blue = $IM_HANDLER->colorAllocate(0,0,255);
#	$COLOR_blue1 = $IM_HANDLER->colorAllocate(0,0,251);
#	$COLOR_blue2 = $IM_HANDLER->colorAllocate(0,0,252);
#	$COLOR_blue3 = $IM_HANDLER->colorAllocate(0,0,253);
#	$COLOR_blue4 = $IM_HANDLER->colorAllocate(0,0,254);
	$COLOR_blue1 = $IM_HANDLER->colorAllocateAlpha(0,0,251,20);
	$COLOR_blue2 = $IM_HANDLER->colorAllocateAlpha(0,0,252,20);
	$COLOR_blue3 = $IM_HANDLER->colorAllocateAlpha(0,0,253,20);
	$COLOR_blue4 = $IM_HANDLER->colorAllocateAlpha(0,0,254,20);
	$COLOR_green = $IM_HANDLER->colorAllocate(0,255,0);
	$COLOR_green1 = $IM_HANDLER->colorAllocate(0,251,0);
	$COLOR_green2 = $IM_HANDLER->colorAllocate(0,252,0);
	$COLOR_green3 = $IM_HANDLER->colorAllocate(0,253,0);
	$COLOR_green4 = $IM_HANDLER->colorAllocate(0,254,0);

	$COLOR_backgroud=$IM_HANDLER->colorAllocate(245,245,245);  # 背景颜色
	$COLOR_darkboder=$IM_HANDLER->colorAllocate(126,126,126);  # 左上边框颜色
	$COLOR_dark=$IM_HANDLER->colorAllocate(126,126,126);  		# 底色
	$COLOR_lightboder=$IM_HANDLER->colorAllocate(203,203,203); # 右上边框颜色

	# Color定义
	
	$COLOR_darkblue=$IM_HANDLER->colorAllocateAlpha(8,46,84,50); # 靛青色
	#$COLOR_green = $IM_HANDLER->colorAllocateAlpha(0,255,0,50);  # Green 透明
	$COLOR_green = $IM_HANDLER->colorAllocate(0,255,0);  # Green 不透明

	# 画一个边框(边框使用2个Pixel)
	$IM_HANDLER->rectangle(0,0,$WIDTH-1,$HEIGHT-1,$COLOR_lightboder);
	$IM_HANDLER->rectangle(1,1,$WIDTH-2,$HEIGHT-2,$COLOR_lightboder);
	$IM_HANDLER->fill(2,2,$COLOR_backgroud);

	# 设置底部阴影边框
	$IM_HANDLER->line(0,$HEIGHT-1,$WIDTH-1,$HEIGHT-1,$COLOR_darkboder);
	# 右边框阴影
	$IM_HANDLER->line($WIDTH-1,0,$WIDTH-1,$HEIGHT-1,$COLOR_darkboder);
		

	
	return 1;
}

sub drawandsavepictures{
	my $item=shift;
	my $scope=shift;
	
	
	my %date=('daily'=>'DDATALOG','weekly'=>'WDATALOG','monthly'=>'MDATALOG','yearly'=>'YDATALOG');
	my $datalog=$date{$scope}; 
	
	print "   [DEBUG] Drawing $scope -> $datalog picture and save it...\n" if($opt_v);
	
	##################################################
	# 处理daily数据，画图平保存PNG文件。
	##################################################
	createimagetemplate() or die "Create Image failed....";  # create a new image
	
	# 获取前1,2,3,4个指标的最大值。

	my @maxvalue=();
	
	for(my $i=1;$i<=8;$i++){
		my $maxkeyname="V".$i."_MAX";
		if($CONFIG{$item}{$maxkeyname} eq ""){
			$maxvalue[$i]=getMaxValue($datalog,$i);
		}else{
			$maxvalue[$i]=$CONFIG{$item}{$maxkeyname};
		}
	}
	print "   [DEBUG] Daily Max_Values: [".join(" ",@maxvalue)." ]\n" if($opt_v);
	
	my $left_max=$maxvalue[1]+$maxvalue[2]+$maxvalue[3]+$maxvalue[4];
	
	# 此处设置一个全局变量，表示Left的刻度。在setAxis() 中设置
	$LEFT1=$left_max/4;
	$LEFT2=$left_max/2;
	$LEFT3=3*$left_max/4;
	$LEFT4=$left_max;
	$left_max=1 if($left_max==0);
	
	# 计算左边 4 个区间的像素值
	my $linespace1=int($PNG_HEIGHT*$maxvalue[1]/$left_max);
	my $linespace2=int($PNG_HEIGHT*$maxvalue[2]/$left_max);
	my $linespace3=int($PNG_HEIGHT*$maxvalue[3]/$left_max);
	my $linespace4=int($PNG_HEIGHT*$maxvalue[4]/$left_max);
	
	# 计算左边 4 个区间分割线所在的像素
	my $line1=int($PNG_TOP+$PNG_HEIGHT-$linespace1);
	my $line2=int($PNG_TOP+$PNG_HEIGHT-$linespace2-$linespace1);
	my $line3=int($PNG_TOP+$PNG_HEIGHT-$linespace3-$linespace2-$linespace1);
	debug("Left seperate: MaxValue:$left_max [$linespace1 $linespace2 $linespace3 $linespace4] -- $line1 $line2 $line3");
	
	my @timeserials=sort {$b <=>$a} (keys(%$datalog));  # 需要进行排序
	

	# 设置X坐标的刻度()
	for(my $i=0;$i<$PNG_WIDTH;$i++){
		my $currenttimetag=$timeserials[$i];  # 获得数轴的时间
		debug("$scope : ( $PNG )".$currenttimetag." -> ".gettime($currenttimetag));
		my ($v1,$v2,$v3,$v4,$v5,$v6,$v7,$v8)=split(/,/,$$datalog{$currenttimetag});  # 获得数轴数据，8个维度
		# 处理第一个指标
		if($maxvalue[1]>0){
			my $percent1=$linespace1*$v1/$maxvalue[1];
			# print $v1."-".int($percent1).".";
			my $from1=$PNG_TOP+$PNG_HEIGHT-int($percent1);
			my $to1=$PNG_TOP+$PNG_HEIGHT;
			setDataBar($i,$from1,$to1,$COLOR_green1);  	# 填充数据，柱状图
		}
		# 处理第二个指标
		if($maxvalue[2]>0){
			my $percent2=$linespace1*$v2/$maxvalue[2];
			my $from2=$PNG_TOP+$PNG_HEIGHT-$linespace1-int($percent2);
			my $to2=$PNG_TOP+$PNG_HEIGHT-$linespace1;
			setDataBar($i,$from2,$to2,$COLOR_green2);  	# 填充数据，柱状图
		}
		if($maxvalue[3]>0){
			my $percent3=$linespace1*$v3/$maxvalue[3];
			my $from3=$PNG_TOP+$PNG_HEIGHT-$linespace1-$linespace2-int($percent3);
			my $to3=$PNG_TOP+$PNG_HEIGHT-$linespace1-$linespace2;
			setDataBar($i,$from3,$to3,$COLOR_green3);  	# 填充数据，柱状图
		}
		if($maxvalue[4]>0){
			my $percent4=$linespace1*$v4/$maxvalue[4];
			my $from4=$PNG_TOP+$PNG_HEIGHT-$linespace1-$linespace2-$linespace3-int($percent4);
			my $to4=$PNG_TOP+$PNG_HEIGHT-$linespace1-$linespace2-$linespace3;
			setDataBar($i,$from4,$to4,$COLOR_green4);  	# 填充数据，柱状图
		}
		
		# 处理第5个指标，在右边的百分比。
		
		if($maxvalue[5]>0){
			my $percent5=int(100*$v5/$maxvalue[5])/100;
			setDataLine($i,$percent5,$COLOR_blue1,5);  	# 填充数据，柱状图
		}
		if($maxvalue[6]>0){
			my $percent6=int(100*$v6/$maxvalue[6])/100;
			setDataLine($i,$percent6,$COLOR_blue2,6);  	# 填充数据，柱状图
		}
		if($maxvalue[7]>0){
			my $percent7=int(100*$v7/$maxvalue[7])/100;
			setDataLine($i,$percent7,$COLOR_blue3,7);  	# 填充数据，柱状图
		}
		if($maxvalue[8]>0){
			my $percent8=int(100*$v8/$maxvalue[8])/100;
			setDataLine($i,$percent8,$COLOR_blue4,8);  	# 填充数据，柱状图
		}		
		
		# 设置 X 方向的步速, Daily 每两个小时一步，Week 每天（24小时）一步，Month 每周一步。 Year，每月一步
		if(isFixedHour($currenttimetag)){
			if($scope eq 'daily'){
				my $myhour=gethour($currenttimetag);
				next if($PNG_DAYLIY>3 && $myhour%2==0);  # 采集的时间如果超过3分钟，则每2小时为一个周期
				setYStepline($i,$myhour);  # 设置步进线和标识,每格 2 小时，否则每小时一格
				
			}elsif($scope eq 'weekly'){
			    my $myhour=gethour($currenttimetag);
				next if($myhour ne '00');  # 采集的时间如果超过3分钟，则每2小时为一个周期
				setYStepline($i,getmday($currenttimetag)."/".getmonth($currenttimetag));  # 设置步进线和标识,每24小时一跟红线。
				
			}elsif($scope eq 'monthly'){
				setYStepline($i,getweek($currenttimetag)) if isFixedWeek4M($currenttimetag);
				#my $myweek=getweek($currenttimetag);
				#next unless($myweek%2==0);  # 采集的时间如果超过3分钟，则每2小时为一个周期
				 # 设置步进线和标识,每24小时一跟红线。
			}elsif($scope eq 'yearly'){
			
			}

		}		
		# 设置红色的周期分割线，天，２４小时，Week: 7 days, Month: 30 days, Year: 365 Days.
		setRedline($i) if($scope eq 'daily' && isFixedDay($currenttimetag));
		setRedline($i) if($scope eq 'weekly' && isFixedWeek($currenttimetag));
		setRedline($i) if($scope eq 'monthly' && isFixedMonth($currenttimetag));
		# setRedline($i) if($scope eq 'yearly' && isFixedWeek($currenttimetag));
	}
	# 画纵向分割线
	drawline($line1);
	drawline($line2);
	drawline($line3);
	
	# 填充数据
	
	# 设置坐标轴，等高线和刻度。
	setAxis();
	
	# 设置标题
	my $title=$item;
	$title=$CONFIG{$item}{NAME} if defined $CONFIG{$item}{NAME};
	$title=~s/\t+$//g;
	setTitle($title." ".gettime(time())." $scope !!! [".$CONFIG{$item}{PNG}."]");
	
	# 保存图像
	saveImage("$item.$scope.png") or die "Same image $item.$scope.png failed....";
	debug("Same image $item.$scope.png Successful....");

}  # draw and same picutres.

# 保存采集的数据
sub savetimedata{
	my $item=shift;
	my $datafilepath=$WORK_DIR."$item.data.log";
	open(DATAFILE, ">",$datafilepath);
	print DATAFILE "$CMD_RESULT\n";
	
	my @keys=keys(%DDATALOG);
	push(@keys,keys(%WDATALOG));
	push(@keys,keys(%MDATALOG));
	push(@keys,keys(%YDATALOG));
	
	undef %hash;
	
	@keys = grep { ++$hash{$_} < 2 } @keys;  # 去除重复
	
	@keys = sort{$b <=> $a} @keys;  # 顺序，时间从大到小排序，越靠前，时间越与现在时间近
	
	print "   [DEBUG] ".scalar @keys." Recorders saved into $datafilepath\n" if($opt_v);
	
	
	# 排序后，将结果输出到log文件中。如果有重复的数据，则Day>Week>Month>Year
	for(my $i=0;$i<scalar @keys;$i++){
		my $values="";
		$values=$YDATALOG{$keys[$i]} if(defined $YDATALOG{$keys[$i]});
		$values=$MDATALOG{$keys[$i]} if(defined $MDATALOG{$keys[$i]});
		$values=$WDATALOG{$keys[$i]} if(defined $WDATALOG{$keys[$i]});
		$values=$DDATALOG{$keys[$i]} if(defined $DDATALOG{$keys[$i]});
		print DATAFILE "$keys[$i],$values\n";
		#print "$keys[$i],$values\n";
		#print "$keys[$i] ".gettime($keys[$i]).": $YDATALOG{$keys[$i]} $MDATALOG{$keys[$i]} $WDATALOG{$keys[$i]} $DDATALOG{$keys[$i]} \n";
	}

	close(DATAFILE);
	
}


# 设置坐标轴

sub setAxis{
	
	# 画坐标轴X axis X & Y
	
	$IM_HANDLER->line($PNG_LEFT,$PNG_TOP,$PNG_LEFT,$PNG_TOP+$PNG_HEIGHT,$COLOR_black);  # Axis Y 
	$IM_HANDLER->line($PNG_LEFT+$PNG_WIDTH,$PNG_TOP,$PNG_LEFT+$PNG_WIDTH,$PNG_TOP+$PNG_HEIGHT,$COLOR_black);  # Axis Y 
		
	$IM_HANDLER->line($PNG_LEFT-2,$PNG_TOP,$PNG_LEFT+$PNG_WIDTH,$PNG_TOP,$COLOR_black); # Axis X  -2 表示添加一个与Y轴的交叉点
	$IM_HANDLER->line($PNG_LEFT-2,$PNG_TOP+$PNG_HEIGHT,$PNG_LEFT+$PNG_WIDTH,$PNG_TOP+$PNG_HEIGHT,$COLOR_black); # Axis X 
	
	$IM_HANDLER->line($PNG_LEFT+$PNG_WIDTH,$PNG_TOP+$PNG_HEIGHT,$PNG_LEFT+$PNG_WIDTH-3,$PNG_TOP+$PNG_HEIGHT-3,$COLOR_red); # Arrow
	$IM_HANDLER->line($PNG_LEFT+$PNG_WIDTH,$PNG_TOP+$PNG_HEIGHT,$PNG_LEFT+$PNG_WIDTH-3,$PNG_TOP+$PNG_HEIGHT+3,$COLOR_red); # Arrow
	
	# 画等高线 RGB(126,126,126) 表示灰色
	
	$IM_HANDLER->dashedLine($PNG_LEFT-2,$PNG_TOP+$PNG_HEIGHT*1/4,$PNG_LEFT+$PNG_WIDTH,$PNG_TOP+$PNG_HEIGHT*1/4,$COLOR_darkboder); # Axis X 
	$IM_HANDLER->dashedLine($PNG_LEFT-2,$PNG_TOP+$PNG_HEIGHT*2/4,$PNG_LEFT+$PNG_WIDTH,$PNG_TOP+$PNG_HEIGHT*2/4,$COLOR_darkboder); # Axis X 
	$IM_HANDLER->dashedLine($PNG_LEFT-2,$PNG_TOP+$PNG_HEIGHT*3/4,$PNG_LEFT+$PNG_WIDTH,$PNG_TOP+$PNG_HEIGHT*3/4,$COLOR_darkboder); # Axis X 
	
	# 设置左边标识
	$IM_HANDLER->string(gdSmallFont,$PNG_LEFT-30,$PNG_TOP-5,human_read_number($LEFT4),$COLOR_black);
	$IM_HANDLER->string(gdSmallFont,$PNG_LEFT-30,$PNG_TOP+$PNG_HEIGHT*1/4-5,human_read_number($LEFT3),$COLOR_black);
	$IM_HANDLER->string(gdSmallFont,$PNG_LEFT-30,$PNG_TOP+$PNG_HEIGHT*2/4-5,human_read_number($LEFT2),$COLOR_black);
	$IM_HANDLER->string(gdSmallFont,$PNG_LEFT-30,$PNG_TOP+$PNG_HEIGHT*3/4-5,human_read_number($LEFT1),$COLOR_black);
	$IM_HANDLER->string(gdSmallFont,$PNG_LEFT-30,$PNG_TOP+$PNG_HEIGHT-5,"   0",$COLOR_black);
	
	# 设置右边百分比标识
	$IM_HANDLER->string(gdSmallFont,$PNG_LEFT+$PNG_WIDTH+3,$PNG_TOP-5,"100%",$COLOR_blue);
	$IM_HANDLER->string(gdSmallFont,$PNG_LEFT+$PNG_WIDTH+3,$PNG_TOP+$PNG_HEIGHT*1/4-5,"75%",$COLOR_blue);
	$IM_HANDLER->string(gdSmallFont,$PNG_LEFT+$PNG_WIDTH+3,$PNG_TOP+$PNG_HEIGHT*2/4-5,"50%",$COLOR_blue);
	$IM_HANDLER->string(gdSmallFont,$PNG_LEFT+$PNG_WIDTH+3,$PNG_TOP+$PNG_HEIGHT*3/4-5,"25%",$COLOR_blue);
	$IM_HANDLER->string(gdSmallFont,$PNG_LEFT+$PNG_WIDTH+3,$PNG_TOP+$PNG_HEIGHT-5,"0%",$COLOR_blue);
}


# 设置图片的标题
sub setTitle{
	my $title=shift;
	$IM_HANDLER->string(gdSmallFont,$PNG_LEFT,5,$title,$COLOR_black);
}

# 纵轴刻度线 输入参数为，第n条竖线。

sub setYStepline{
	my $steps=shift;  # 从右向左，第n条
	my $title=shift;
	my $from_x=$WIDTH-$PNG_RIGHT-1-$steps; # 起始点
	my $to_x=$fromx; # 起始点
	my $from_y=$PNG_TOP; 
	my $to_y=$PNG_TOP+$PNG_HEIGHT;
	$IM_HANDLER->dashedLine($from_x,$from_y,$from_x,$to_y,$COLOR_dark); 
	$IM_HANDLER->string(gdSmallFont,$from_x-3,$to_y+2,$title,$COLOR_black);
}


# 设置天的分割线,红色显示

sub setRedline{
	my $steps=shift;  # 从右向左，第n条
	my $from_x=$WIDTH-$PNG_RIGHT-1-$steps; # 起始点
	my $to_x=$fromx; # 起始点
	my $from_y=$PNG_TOP; 
	my $to_y=$PNG_TOP+$PNG_HEIGHT;
	$IM_HANDLER->line($from_x,$from_y,$from_x,$to_y,$COLOR_red); 
}

# 画横线

sub drawline{
	my $line=shift;  # 从右向左，第n条
	my $from_x=$PNG_LEFT-1; # 起始点
	my $from_y=$line; 
	my $to_x=$from_x+$PNG_WIDTH+1; # 起始点
	my $to_y=$line;
	$IM_HANDLER->line($from_x,$from_y,$to_x,$to_y,$COLOR_red); 
}

# 纵轴刻度线 输入参数为，第n条竖线。

sub setDataBar{
	my $steps=shift;  # 从右向左，第n条
	my $from_y=shift;
	my $to_y=shift;
	my $color=shift;
	my $from_x=$WIDTH-$PNG_RIGHT-1-$steps; # 起始点
	my $to_x=$fromx; # 起始点
	$IM_HANDLER->line($from_x,$from_y,$from_x,$to_y,$color); 
}

sub setDataBar_old{
	my $steps=shift;  # 从右向左，第n条
	my $post=shift;
	my $from_x=$WIDTH-$PNG_RIGHT-1-$steps; # 起始点
	my $to_x=$fromx; # 起始点
	my $from_y=$PNG_TOP+$PNG_HEIGHT*$post; 
	my $to_y=$PNG_TOP+$PNG_HEIGHT-1;
	$IM_HANDLER->line($from_x,$from_y,$from_x,$to_y,$COLOR_green); 
}

# 设置线图

sub setDataLine{
	my $steps=shift;  # 从右向左，第n条
	my $post=shift;
	my $color=shift;
	my $dim=shift;  # 第几根线。
	if($steps==0){ # 第一不画线，记录后直接退出。
		$LASTPOINT[$dim]=$PNG_TOP+$PNG_HEIGHT-int($PNG_HEIGHT*$post);
		return(0);
	}

	my $x1=$WIDTH-$PNG_RIGHT-1-$steps; # 起始点
	my $x2=$x1-1; # 终止点X坐标，比起始点小一个像素
	my $y1=$LASTPOINT[$dim]; 
	my $y2=$PNG_TOP+$PNG_HEIGHT-int($PNG_HEIGHT*$post);  # 上移一个像素。
	
#	if($steps%5==0){
#		print "$x1,$y1,$x2,$y2-$color\n"
#	}else{
#		print "$x1,$y1,$x2,$y2-$color\t"
#	}
	$IM_HANDLER->line($x1,$y1,$x2,$y2,$color); 
	$LASTPOINT[$dim]=$y2; #记录上次位置。
}

# 保存png文件

sub saveImage{
	$imagename=shift;
	open(PNGOUT, ">",$WORK_DIR."/".$imagename);     
	binmode PNGOUT;
	# Convert the image to PNG and print it on standard output
	print PNGOUT $IM_HANDLER->png;
	close(PNGOUT);
	return 1;
}
################################
# Get the Max value from hash data metrix

sub getMaxValue{
	my $DWMY=shift;  #  DDATALOG WDATALOG MDATALOG YDATALOG
	my $position=shift;  # 8个维度中的那个？
	my @allvalues=();
	# print "$DWMY, $position \n";
	
	    if(uc($DWMY) eq "DDATALOG"){
		@allvalues=values(%DDATALOG)
	}elsif(uc($DWMY) eq "WDATALOG"){
		@allvalues=values(%WDATALOG)
	}elsif(uc($DWMY) eq "MDATALOG"){
		@allvalues=values(%MDATALOG)
	}elsif(uc($DWMY) eq "YDATALOG"){
		@allvalues=values(%YDATALOG)
	}else{
		@allvalues=();
	}
	
	my $thereturnvalue=0;
	# print "@allvalues\n";
	
	foreach my $eachline(@allvalues){
		# print $eachline;
		my @sparatevalue=split(/,/,$eachline);
		$thereturnvalue=$sparatevalue[$position-1] if($sparatevalue[$position-1] > $thereturnvalue);
	}
	return $thereturnvalue;
}

################################
# return a human readable nubmer.

sub human_read_number{
	my $inputnumber=shift;
	return 0.0 unless defined $inputnumber;
	if($inputnumber>0 and $inputnumber<1000){
		return sprintf("% 4d",$inputnumber);
	}elsif($inputnumber>=1000 and $inputnumber<1000000){
		return sprintf("% 3dK",$inputnumber/1000);
	}elsif($inputnumber>=1000000 and $inputnumber<1000000000){
		return sprintf("% 3dM",$inputnumber/1000000);
	}elsif($inputnumber>=1000000000 and $inputnumber<1000000000000){
		return sprintf("% 3dG",$inputnumber/1000000000);
	}elsif($inputnumber>=1000000000000 and $inputnumber<1000000000000000){
		return sprintf("% 3dT",$inputnumber/1000000000000);
	}else{
		return $inputnumber;
	}
}


################################
# Rewrite the HTML

sub updatehtml{
	my $item=shift;
	my $now=gettime(time());
	my $HTML=join(undef,@HTML_TEMP);
	# 开始替换 {TITLE} 和 {name}
	$HTML=~s/{TITLE}/$item/g;
	$HTML=~s/{name}/$item/g;
	$HTML=~s/{TIME}/$now/g;
	
	$HTML=~s/{dm}/$PNG_DAYLIY/g;
	$HTML=~s/{wm}/$PNG_WEEKLY/g;
	$HTML=~s/{mm}/$PNG_MONTHLY/g;
	$HTML=~s/{ym}/$PNG_YEARLY/g;
	open(HTMLFILE, ">",$WORK_DIR."/$item.html");
	print HTMLFILE $HTML;
	close(HTMLFILE);
	print "   [DEBUG] Update the HTML $WORK_DIR$item.html (lenght: ". length($HTML).")\n" if($opt_v);

}

###########################
# debug(infomation)
sub debug{
	$message=shift;
	print "   [DEBUG] $message\n"  if($opt_v);
}

__DATA__
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/dtd/xhtml11.dtd">
<html>
	<head>
		<title>{TITLE}</title>
		<meta http-equiv="refresh" content="300" />
		<meta http-equiv="pragma" content="no-cache" />
		<meta http-equiv="cache-control" content="no-cache" />
		<style type="text/css">
			body 	{background-color: #ffffff;}
			div 	{border-bottom: 2px solid #aaa;padding-bottom: 10px;margin-bottom: 5px;}
			div h2 	{font-size: 1.2em;}
			div.graph img {margin: 5px 0;}
			div.graph table, div#legend table {font-size: .8em;}
			div.graph table td {padding: 0 10px;text-align: right;}
			div table .in th, div table td span.in {color: #00cc00;}
			div table .out th, div table td span.out {color: #0000ff;}
			div#legend th {	text-align: right;}
			div#footer {border: none;font-size: .8em;font-family: Arial, Helvetica, sans-serif;	width: 476px;}
			div#footer img {border: none;height: 25px;}
			div#footer address {text-align: right;}
			div#footer #version {margin: 0;padding: 0;float: left;width: 88px;text-align: right;}
		</style>
	</head>
<body>
<h1>{TITLE}</h1>
<p>The statistics were last updated <strong>{TIME}</strong></p>
		<div class="graph">
			<h2>`Daily' Graph ( each {dm} Minutes)</h2>
			<img src="{name}.daily.png" title="day" alt="day" />
		</div>
		<div class="graph">
			<h2>`Weekly' Graph (each {wm} Minutes)</h2>
			<img src="{name}.weekly.png" title="week" alt="week" />
		</div>
		<div class="graph">
			<h2>`Monthly' Graph (each {mm} Minutes)</h2>
			<img src="{name}.monthly.png" title="month" alt="month" />
		</div>
		<div class="graph">
			<h2>`Yearly' Graph (each {ym} Minutes)</h2>
			<img src="{name}.yearly.png" title="year" alt="year" />
		</div>
		<div id="legend">
			<table>
				<tr class="in">
					<th scope="row">GREEN ###</th>
					<td>Incoming Traffic in Bytes per Second</td>
				</tr>
				<tr class="out">
					<th scope="row">BLUE ###</th>
					<td>Outgoing Traffic in Bytes per Second</td>
				</tr>
			</table>
		</div>
		<div id="footer">
			<a href="http://oss.oetiker.ch/mrtg/"><img src="mrtg-l.png" width="63" title="MRTG" alt="MRTG" /><img src="mrtg-m.png" width="25" title="MRTG" alt="MRTG" /><img src="mrtg-r.png" width="388" title="Multi Router Traffic Grapher" alt="Multi Router Traffic Grapher" /></a>
			<p id="version">2.17.4</p>
		</div>
	</body>
</html>